/*
 * CC3OpenGLES11Lighting.m
 *
 * cocos3d 0.6.1
 * Author: Bill Hollings
 * Copyright (c) 2010-2011 The Brenwill Workshop Ltd. All rights reserved.
 * http://www.brenwill.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * http://en.wikipedia.org/wiki/MIT_License
 * 
 * See header file CC3OpenGLES11Lighting.h for full API documentation.
 */

#include "CC3OpenGLES11Lighting.h"
#include "CC3OpenGLES11Engine.h" 


#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerLightFloat

//@implementation CC3OpenGLES11StateTrackerLightFloat
//
//@synthesize lightIndex;
//
//-(GLenum) glLightIndex {
//	return GL_LIGHT0 + lightIndex;
//}
//
//-(id) initForState: (GLenum) qName andLightIndex: (GLuint) ltIndx {
//	if ( (self = [super initForState: qName]) ) {
//		lightIndex = ltIndx;
//	}
//	return self;
//}
//
//+(id) trackerForState: (GLenum) qName andLightIndex: (GLuint) ltIndx {
//	return [[[self alloc] initForState: qName andLightIndex: ltIndx] autorelease];
//}
//
//-(void) getGLValue {
//	glGetLightfv(self.glLightIndex, name, (GLfloat*)&originalValue);
//}
//
//-(void) logGetGLValue {
//	LogTrace("%@ %@ %@ read GL value %.2f (was tracking %@)",
//			 [self class], NSStringFromGLEnum(self.glLightIndex), NSStringFromGLEnum(name),
//			 originalValue, (valueIsKnown ? [NSString stringWithFormat: @"%.2f", value] : @"UNKNOWN"));
//}
//
//-(void) setGLValue {
//	glLightf(self.glLightIndex, name, value);
//}
//
//-(void) logSetValue: (BOOL) wasSet {
//	LogTrace("%@ %@ %@ %@ = %.2f", [self class], NSStringFromGLEnum(self.glLightIndex),
//			 (wasSet ? @"set" : @"reused"), NSStringFromGLEnum(name), value);
//}
//
//@end

CC3OpenGLES11StateTrackerLightFloat::CC3OpenGLES11StateTrackerLightFloat()
{
}

CC3OpenGLES11StateTrackerLightFloat::~CC3OpenGLES11StateTrackerLightFloat()
{
}

CC3OpenGLES11StateTrackerLightFloat* CC3OpenGLES11StateTrackerLightFloat::trackerForState(GLenum qName, GLuint ltIndx)
{
	CC3OpenGLES11StateTrackerLightFloat* pState = new CC3OpenGLES11StateTrackerLightFloat;
	if (pState) 
	{
		pState->initForState(qName, ltIndx);
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11StateTrackerLightFloat* CC3OpenGLES11StateTrackerLightFloat::initForState(GLenum qName, GLuint ltIndx)
{
	if (CC3OpenGLES11StateTrackerFloat::initForState(qName, NULL)) 
	{
		lightIndex = ltIndx;
	} 
	
	return this;
}

GLenum CC3OpenGLES11StateTrackerLightFloat::glLightIndex()
{
	return GL_LIGHT0 + lightIndex;
}

void CC3OpenGLES11StateTrackerLightFloat::getGLValue()
{
	glGetLightfv(glLightIndex(), name, (GLfloat*)&originalValue);
}

void CC3OpenGLES11StateTrackerLightFloat::logGetGLValue()
{
}

void CC3OpenGLES11StateTrackerLightFloat::setGLValue()
{
	glLightf(glLightIndex(), name, value);
}

void CC3OpenGLES11StateTrackerLightFloat::logSetValue(bool wasSet)
{
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerLightColor

//@implementation CC3OpenGLES11StateTrackerLightColor
//
//@synthesize lightIndex;
//
//-(GLenum) glLightIndex {
//	return GL_LIGHT0 + lightIndex;
//}
//
//-(id) initForState: (GLenum) qName andLightIndex: (GLuint) ltIndx {
//	if ( (self = [super initForState: qName]) ) {
//		lightIndex = ltIndx;
//	}
//	return self;
//}
//
//+(id) trackerForState: (GLenum) qName andLightIndex: (GLuint) ltIndx {
//	return [[[self alloc] initForState: qName andLightIndex: ltIndx] autorelease];
//}
//
//-(void) getGLValue {
//	glGetLightfv(self.glLightIndex, name, (GLfloat*)&originalValue);
//}
//
//-(void) logGetGLValue {
//	LogTrace("%@ %@ %@ read GL value %@ (was tracking %@)", 
//			 [self class], NSStringFromGLEnum(self.glLightIndex), NSStringFromGLEnum(name),
//			 NSStringFromCCC4F(originalValue), (valueIsKnown ? NSStringFromCCC4F(value) : @"UNKNOWN"));
//}
//
//-(void) setGLValue {
//	glLightfv(self.glLightIndex, name, (GLfloat*)&value);
//}
//
//-(void) logSetValue: (BOOL) wasSet {
//	LogTrace("%@ %@ %@ %@ = %@", [self class], NSStringFromGLEnum(self.glLightIndex),
//			 (wasSet ? @"set" : @"reused"), NSStringFromGLEnum(name), NSStringFromCCC4F(value));
//}
//
//@end

CC3OpenGLES11StateTrackerLightColor::CC3OpenGLES11StateTrackerLightColor()
{
}

CC3OpenGLES11StateTrackerLightColor::~CC3OpenGLES11StateTrackerLightColor()
{
}

CC3OpenGLES11StateTrackerLightColor* CC3OpenGLES11StateTrackerLightColor::trackerForState(GLenum qName, GLuint ltIndx)
{
	CC3OpenGLES11StateTrackerLightColor* pState = new CC3OpenGLES11StateTrackerLightColor;
	if (pState) 
	{
		pState->initForState(qName, ltIndx);
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11StateTrackerLightColor* CC3OpenGLES11StateTrackerLightColor::initForState(GLenum qName, GLuint ltIndx)
{
	if (CC3OpenGLES11StateTrackerColor::initForState(qName, NULL)) 
	{
		lightIndex = ltIndx;
	} 
	
	return this;
}

GLenum CC3OpenGLES11StateTrackerLightColor::glLightIndex()
{
	return GL_LIGHT0 + lightIndex;
}

void CC3OpenGLES11StateTrackerLightColor::getGLValue()
{
	glGetLightfv(glLightIndex(), name, (GLfloat*)&originalValue);
}

void CC3OpenGLES11StateTrackerLightColor::logGetGLValue()
{
}

void CC3OpenGLES11StateTrackerLightColor::setGLValue()
{
	glLightfv(glLightIndex(), name, (GLfloat*)&value);
}

void CC3OpenGLES11StateTrackerLightColor::logSetValue(bool wasSet)
{
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerLightVector

//@implementation CC3OpenGLES11StateTrackerLightVector
//
//@synthesize lightIndex;
//
//-(GLenum) glLightIndex {
//	return GL_LIGHT0 + lightIndex;
//}
//
//-(id) initForState: (GLenum) qName andLightIndex: (GLuint) ltIndx {
//	if ( (self = [super initForState: qName]) ) {
//		lightIndex = ltIndx;
//	}
//	return self;
//}
//
//+(id) trackerForState: (GLenum) qName andLightIndex: (GLuint) ltIndx {
//	return [[[self alloc] initForState: qName andLightIndex: ltIndx] autorelease];
//}
//
//-(void) getGLValue {
//	glGetLightfv(self.glLightIndex, name, (GLfloat*)&originalValue);
//}
//
//-(void) logGetGLValue {
//	LogTrace("%@ %@ %@ read GL value %@ (was tracking %@)", 
//			 [self class], NSStringFromGLEnum(self.glLightIndex), NSStringFromGLEnum(name),
//			 NSStringFromCC3Vector(originalValue), (valueIsKnown ? NSStringFromCC3Vector(value) : @"UNKNOWN"));
//}
//
//-(void) setGLValue {
//	glLightfv(self.glLightIndex, name, (GLfloat*)&value);
//}
//
//-(void) logSetValue: (BOOL) wasSet {
//	LogTrace("%@ %@ %@ %@ = %@", [self class], NSStringFromGLEnum(self.glLightIndex),
//			 (wasSet ? @"set" : @"reused"), NSStringFromGLEnum(name), NSStringFromCC3Vector(value));
//}
//
//@end

CC3OpenGLES11StateTrackerLightVector::CC3OpenGLES11StateTrackerLightVector()
{
}

CC3OpenGLES11StateTrackerLightVector::~CC3OpenGLES11StateTrackerLightVector()
{
}

CC3OpenGLES11StateTrackerLightVector* CC3OpenGLES11StateTrackerLightVector::trackerForState(GLenum qName, GLuint ltIndx)
{
	CC3OpenGLES11StateTrackerLightVector* pState = new CC3OpenGLES11StateTrackerLightVector;
	if (pState) 
	{
		pState->initForState(qName, ltIndx);
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11StateTrackerLightVector* CC3OpenGLES11StateTrackerLightVector::initForState(GLenum qName, GLuint ltIndx)
{
	if (CC3OpenGLES11StateTrackerVector::initForState(qName)) 
	{
		lightIndex = ltIndx;
	} 
	
	return this;
}

GLenum CC3OpenGLES11StateTrackerLightVector::glLightIndex()
{
	return GL_LIGHT0 + lightIndex;
}

void CC3OpenGLES11StateTrackerLightVector::getGLValue()
{
	glGetLightfv(glLightIndex(), name, (GLfloat*)&originalValue);
}

void CC3OpenGLES11StateTrackerLightVector::logGetGLValue()
{
}

void CC3OpenGLES11StateTrackerLightVector::setGLValue()
{
	glLightfv(glLightIndex(), name, (GLfloat*)&value);
}

void CC3OpenGLES11StateTrackerLightVector::logSetValue(bool wasSet)
{
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerLightVector4

//@implementation CC3OpenGLES11StateTrackerLightVector4
//
//@synthesize lightIndex;
//
//-(GLenum) glLightIndex {
//	return GL_LIGHT0 + lightIndex;
//}
//
//-(id) initForState: (GLenum) qName andLightIndex: (GLuint) ltIndx {
//	if ( (self = [super initForState: qName]) ) {
//		lightIndex = ltIndx;
//	}
//	return self;
//}
//
//+(id) trackerForState: (GLenum) qName andLightIndex: (GLuint) ltIndx {
//	return [[[self alloc] initForState: qName andLightIndex: ltIndx] autorelease];
//}
//
//-(void) getGLValue {
//	glGetLightfv(self.glLightIndex, name, (GLfloat*)&originalValue);
//}
//
//-(void) logGetGLValue {
//	LogTrace("%@ %@ %@ read GL value %@ (was tracking %@)", 
//			 [self class], NSStringFromGLEnum(self.glLightIndex), NSStringFromGLEnum(name),
//			 NSStringFromCC3Vector4(originalValue), (valueIsKnown ? NSStringFromCC3Vector4(value) : @"UNKNOWN"));
//}
//
//-(void) setGLValue {
//	glLightfv(self.glLightIndex, name, (GLfloat*)&value);
//}
//
//-(void) logSetValue: (BOOL) wasSet {
//	LogTrace("%@ %@ %@ %@ = %@", [self class], NSStringFromGLEnum(self.glLightIndex),
//			 (wasSet ? @"set" : @"reused"), NSStringFromGLEnum(name), NSStringFromCC3Vector4(value));
//}
//
//@end

CC3OpenGLES11StateTrackerLightVector4::CC3OpenGLES11StateTrackerLightVector4()
{
}

CC3OpenGLES11StateTrackerLightVector4::~CC3OpenGLES11StateTrackerLightVector4()
{
}

CC3OpenGLES11StateTrackerLightVector4* CC3OpenGLES11StateTrackerLightVector4::trackerForState(GLenum qName, GLuint ltIndx)
{
	CC3OpenGLES11StateTrackerLightVector4* pState = new CC3OpenGLES11StateTrackerLightVector4;
	if (pState) 
	{
		pState->initForState(qName, ltIndx);
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11StateTrackerLightVector4* CC3OpenGLES11StateTrackerLightVector4::initForState(GLenum qName, GLuint ltIndx)
{
	if (CC3OpenGLES11StateTrackerVector4::initForState(qName)) 
	{
		lightIndex = ltIndx;
	} 
	
	return this;
}

GLenum CC3OpenGLES11StateTrackerLightVector4::glLightIndex()
{
	return GL_LIGHT0 + lightIndex;
}

void CC3OpenGLES11StateTrackerLightVector4::getGLValue()
{
	glGetLightfv(glLightIndex(), name, (GLfloat*)&originalValue);
}

void CC3OpenGLES11StateTrackerLightVector4::logGetGLValue()
{
}

void CC3OpenGLES11StateTrackerLightVector4::setGLValue()
{
	glLightfv(glLightIndex(), name, (GLfloat*)&value);
}

void CC3OpenGLES11StateTrackerLightVector4::logSetValue(bool wasSet)
{
}

#pragma mark -
#pragma mark CC3OpenGLES11Light

//@implementation CC3OpenGLES11Light
//
//@synthesize light;
//@synthesize ambientColor;
//@synthesize diffuseColor;
//@synthesize specularColor;
//@synthesize position;
//@synthesize spotDirection;
//@synthesize spotCutoffAngle;
//@synthesize constantAttenuation;
//@synthesize linearAttenuation;
//@synthesize quadraticAttenuation;
//
//-(void) dealloc {
//	[light release];
//	[ambientColor release];
//	[diffuseColor release];
//	[specularColor release];
//	[position release];
//	[spotDirection release];
//	[spotCutoffAngle release];
//	[constantAttenuation release];
//	[linearAttenuation release];
//	[quadraticAttenuation release];
//	[super dealloc];
//}
//
//-(id) initWithLightIndex: (GLuint) ltIndx {
//	if ( (self = [super initMinimal]) ) {
//		lightIndex = ltIndx;
//		[self initializeTrackers];
//	}
//	return self;
//}
//
//+(id) trackerWithLightIndex: (GLuint) ltIndx {
//	return [[[self alloc] initWithLightIndex: ltIndx] autorelease];
//}
//
//-(void) initializeTrackers {
//	self.light = [CC3OpenGLES11StateTrackerServerCapability trackerForState: GL_LIGHT0 + lightIndex];
//	self.ambientColor = [CC3OpenGLES11StateTrackerLightColor trackerForState: GL_AMBIENT andLightIndex: lightIndex];
//	self.diffuseColor = [CC3OpenGLES11StateTrackerLightColor trackerForState: GL_DIFFUSE andLightIndex: lightIndex];
//	self.specularColor = [CC3OpenGLES11StateTrackerLightColor trackerForState: GL_SPECULAR andLightIndex: lightIndex];
//	self.position = [CC3OpenGLES11StateTrackerLightVector4 trackerForState: GL_POSITION andLightIndex: lightIndex];
//	self.spotDirection = [CC3OpenGLES11StateTrackerLightVector trackerForState: GL_SPOT_DIRECTION andLightIndex: lightIndex];
//	self.spotCutoffAngle = [CC3OpenGLES11StateTrackerLightFloat trackerForState: GL_SPOT_CUTOFF andLightIndex: lightIndex];
//	self.constantAttenuation = [CC3OpenGLES11StateTrackerLightFloat trackerForState: GL_CONSTANT_ATTENUATION andLightIndex: lightIndex];
//	self.linearAttenuation = [CC3OpenGLES11StateTrackerLightFloat trackerForState: GL_LINEAR_ATTENUATION andLightIndex: lightIndex];
//	self.quadraticAttenuation = [CC3OpenGLES11StateTrackerLightFloat trackerForState: GL_QUADRATIC_ATTENUATION andLightIndex: lightIndex];
//}
//
//-(void) open {
//	LogTrace("Opening %@", [self class]);
//	[light open];
//	[ambientColor open];
//	[diffuseColor open];
//	[specularColor open];
//	[position open];
//	[spotDirection open];
//	[spotCutoffAngle open];
//	[constantAttenuation open];
//	[linearAttenuation open];
//	[quadraticAttenuation open];
//}
//
//-(void) close {
//	LogTrace("Closing %@", [self class]);
//	[light close];
//	[ambientColor close];
//	[diffuseColor close];
//	[specularColor close];
//	[position close];
//	[spotDirection close];
//	[spotCutoffAngle close];
//	[constantAttenuation close];
//	[linearAttenuation close];
//	[quadraticAttenuation close];
//}
//
//@end

CC3OpenGLES11Light::CC3OpenGLES11Light()
{
}

CC3OpenGLES11Light::~CC3OpenGLES11Light()
{
	light->release();
	ambientColor->release();
	diffuseColor->release();
	specularColor->release();
	position->release();
	spotDirection->release();
	spotCutoffAngle->release();
	constantAttenuation->release();
	linearAttenuation->release();
	quadraticAttenuation->release();
}

CC3OpenGLES11Light* CC3OpenGLES11Light::trackerWithLightIndex(GLuint ltIndx)
{
	CC3OpenGLES11Light* pLight = new CC3OpenGLES11Light;
	if (pLight) 
	{
		pLight->initWithLightIndex(ltIndx);
		pLight->autorelease();
	}
	
	return pLight;
}

CC3OpenGLES11Light* CC3OpenGLES11Light::initWithLightIndex(GLuint ltIndx)
{
	if (CC3OpenGLES11StateTrackerManager::initMinimal()) 
	{
		lightIndex = ltIndx;
		initializeTrackers();
	} 
	return this;
}

void CC3OpenGLES11Light::open()
{
	//LogTrace("Opening %@", [self class]);
	light->open();
	ambientColor->open();
	diffuseColor->open();
	specularColor->open();
	position->open();
	spotDirection->open();
	spotCutoffAngle->open();
	constantAttenuation->open();
	linearAttenuation->open();
	quadraticAttenuation->open();
}

void CC3OpenGLES11Light::close()
{
	//LogTrace("Closing %@", [self class]);
	light->close();
	ambientColor->close();
	diffuseColor->close();
	specularColor->close();
	position->close();
	spotDirection->close();
	spotCutoffAngle->close();
	constantAttenuation->close();
	linearAttenuation->close();
	quadraticAttenuation->close();
}

void CC3OpenGLES11Light::initializeTrackers()
{
	setLight(CC3OpenGLES11StateTrackerServerCapability::trackerForState(GL_LIGHT0 + lightIndex));
	setAmbientColor(CC3OpenGLES11StateTrackerLightColor::trackerForState(GL_AMBIENT, lightIndex));
	setDiffuseColor(CC3OpenGLES11StateTrackerLightColor::trackerForState(GL_DIFFUSE, lightIndex));
	setSpecularColor(CC3OpenGLES11StateTrackerLightColor::trackerForState(GL_SPECULAR, lightIndex));
	setPosition(CC3OpenGLES11StateTrackerLightVector4::trackerForState(GL_POSITION, lightIndex));
	setSpotDirection(CC3OpenGLES11StateTrackerLightVector::trackerForState(GL_SPOT_DIRECTION, lightIndex));
	setSpotCutoffAngle(CC3OpenGLES11StateTrackerLightFloat::trackerForState(GL_SPOT_CUTOFF, lightIndex));
	setConstantAttenuation(CC3OpenGLES11StateTrackerLightFloat::trackerForState(GL_CONSTANT_ATTENUATION, lightIndex));
	setLinearAttenuation(CC3OpenGLES11StateTrackerLightFloat::trackerForState(GL_LINEAR_ATTENUATION, lightIndex));
	setQuadraticAttenuation(CC3OpenGLES11StateTrackerLightFloat::trackerForState(GL_QUADRATIC_ATTENUATION, lightIndex));
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerWorldLightColor

//@implementation CC3OpenGLES11StateTrackerWorldLightColor
//
//-(void) setGLValue {
//	glLightModelfv(name, (GLfloat*)&value);
//}
//
//@end

CC3OpenGLES11StateTrackerWorldLightColor* CC3OpenGLES11StateTrackerWorldLightColor::trackerForState(GLenum aName)
{
	CC3OpenGLES11StateTrackerWorldLightColor* pState = new CC3OpenGLES11StateTrackerWorldLightColor;
	if (pState) 
	{
		pState->initForState(aName, NULL);
		pState->autorelease();
	}
	
	return pState;
}

void CC3OpenGLES11StateTrackerWorldLightColor::setGLValue()
{
	glLightModelfv(name, (GLfloat*)&value);
}

#pragma mark -
#pragma mark CC3OpenGLES11Lighting

//@implementation CC3OpenGLES11Lighting
//
//@synthesize worldAmbientLight, lights;
//
//-(void) dealloc {
//	[worldAmbientLight release];
//	[lights release];
//	[super dealloc];
//}
//
//-(GLuint) lightCount {
//	return lights ? lights.count : 0;
//}
//
//-(CC3OpenGLES11Light*) lightAt: (GLuint) ltIndx {
//	// If the requested light hasn't been allocated yet, add it.
//	if (ltIndx >= self.lightCount) {
//		// Make sure we don't add beyond the max number of texture units for the platform
//		GLuint platformMaxLights = [CC3OpenGLES11Engine engine].platform.maxLights.value;
//		GLuint ltMax = MIN(ltIndx, platformMaxLights);
//		
//		// Add all lights between the current count and the requested texture unit.
//		for (GLuint i = self.lightCount; i <= ltMax; i++) {
//			CC3OpenGLES11Light* lt = [CC3OpenGLES11Light trackerWithLightIndex: i];
//			[lt open];		// Read the initial values
//			[lights addObject: lt];
//			LogTrace(@"%@ added light %u: %@", [self class], i, lt);
//		}
//	}
//	return [lights objectAtIndex: ltIndx];
//}
//
//-(void) initializeTrackers {
//	self.worldAmbientLight = [CC3OpenGLES11StateTrackerWorldLightColor trackerForState: GL_LIGHT_MODEL_AMBIENT];
//	self.lights = [NSMutableArray array];		// Start with none. Add them as requested.
//}
//
//-(void) open {
//	LogTrace("Opening %@", [self class]);
//	[worldAmbientLight open];
//	[self openTrackers: lights];
//}
//
//-(void) close {
//	LogTrace("Closing %@", [self class]);
//	[worldAmbientLight close];
//	[self closeTrackers: lights];
//}
//
//-(NSString*) description {
//	NSMutableString* desc = [NSMutableString stringWithCapacity: 400];
//	[desc appendFormat: @"%@:", [self class]];
//	[desc appendFormat: @"\n    %@ ", worldAmbientLight];
//	for (id t in lights) {
//		[desc appendFormat: @"\n    %@ ", t];
//	}
//	return desc;
//}
//
//@end

CC3OpenGLES11Lighting::CC3OpenGLES11Lighting()
{
	
}

CC3OpenGLES11Lighting::~CC3OpenGLES11Lighting()
{
	worldAmbientLight->release();
	lights->release();
}

CC3OpenGLES11Lighting* CC3OpenGLES11Lighting::tracker()
{
	CC3OpenGLES11Lighting* pState = new CC3OpenGLES11Lighting;
	if (pState) 
	{
		pState->initializeTrackers();
		pState->autorelease();
	}
	
	return pState;
}

CC3OpenGLES11Light* CC3OpenGLES11Lighting::lightAt(GLuint ltIndx)
{
	if (ltIndx >= lightCount()) 
	{
		// Make sure we don't add beyond the max number of texture units for the platform
		GLuint platformMaxLights = CC3OpenGLES11Engine::engine()->getPlatform()->getMaxLights()->getValue();
		GLuint ltMax = MIN(ltIndx, platformMaxLights);
		
		// Add all lights between the current count and the requested texture unit.
		for (GLuint i = lightCount(); i <= ltMax; i++) 
		{
			CC3OpenGLES11Light* lt = CC3OpenGLES11Light::trackerWithLightIndex(i);
			if (lt) 
			{
				lt->open();		// Read the initial values
				lights->addObject(lt);
				//LogTrace(@"%@ added light %u: %@", [self class], i, lt);
			}
		}
	}
	
	return (CC3OpenGLES11Light*)(lights->objectAtIndex(ltIndx));
}

GLuint CC3OpenGLES11Lighting::lightCount()
{
	return lights ? lights->count() : 0;
}

void CC3OpenGLES11Lighting::open()
{
	//LogTrace("Opening %@", [self class]);
	worldAmbientLight->open();
	openTrackers(lights);
}

void CC3OpenGLES11Lighting::close()
{
	//LogTrace("Closing %@", [self class]);
	worldAmbientLight->close();
	closeTrackers(lights);
}

void CC3OpenGLES11Lighting::initializeTrackers()
{
	setWorldAmbientLight(CC3OpenGLES11StateTrackerWorldLightColor::trackerForState(GL_LIGHT_MODEL_AMBIENT));
	lights = cocos2d::CCArray::array();		// Start with none. Add them as requested.
	lights->retain();
}

